<?php
/**
 * @file /Db/Statement/mysql.php
 *
 * Statement representation of MySQL-Querys.
 *
 * @copydoc Db_Statement
 *
 * http://code.google.com/p/rpd/wiki/mysql.php
 *
 * New BSD License
 * \n
 * Copyright (c) 2010 Rpd-Team
 *
 * @namespace  rpd
 * @since      0.1.0
 * @version    0.1.0
 */

/**
 *
 */

class Db_Statement_mysql extends    Db_Statement_Abstract
                         implements Db_Statement_Interface {
                         	
    public function __get($parameter)
    {
    	return $this->_map[$parameter];
    }
                         	
	public function __invoke($in)
    {
    	foreach ($in as $param => $value)
    	{
    		$this->__set($param, $value);
    	}
    }
    
    public function __set($parameter, $value)
    {
    	if (isset($this->_map[$parameter]))
    	{
    	   	$this->_map[$parameter] = &$value;
    	}
    	/**
    	 * @todo A1104 throw notice if param not found / set
    	 */
    }
    
    function _quote($unescaped)
	{
		if (is_scalar($unescaped))
		{
			if (is_string($unescaped))
			{
				return "'"
				     . mysql_real_escape_string($unescaped, $this->_link)
				     . "'";
			}
			else
			{
				return mysql_real_escape_string($unescaped, $this->_link);
			}
		}
		
		return $this->quote(serialize($unescaped));
	}
                         	
	public function bindColumn($column, &$variable)
    {
    	$variable = &$this->__get($column);
    }
    
    public function bindParameter($parameter, &$variable)
    {
    	$this->__set($column, &$variable);
    }
    
    public function current()
    {
    	return $this->_current;
    }
	
	public function countRows()
	{
		if (is_resource($this->_result))
		{
			return mysql_num_rows($this->_result);
		}
		else
		{
			return $this->_valid;
		}
		return 0;
	}
	
	public function errorCode()
	{
		return $this->_error["code"];
	}
	
    public function errorMessage()
	{
		return $this->_error["message"];
	}
	
	
	public function execute()
	{
		if (!empty($this->_map))
		{
			$query = $this->_statement;
			foreach ($this->_map as $key => $value)
			{
				$value = $this->_quote($value);
				mysql_query("SET @$key = " . $value);
				dump(true, "SET @$key = " . $value);
			}
			
			$variables = implode(", @", array_keys($this->_map));
			
			$this->_result = mysql_query("EXECUTE `" . $this->_statementName
			                            . "` USING @$variables") or die(mysql_error());
			                            
			if ($this->_result === true)
			{
				$this->_valid = mysql_affected_rows($this->_link);
			}                            
		}
		else 
		{
			$this->_result = mysql_query($this->_statement, $this->_link);
			if ($this->_result === true)
			{
				$this->_valid = true;
			}
			else 
			{
				$this->_valid = mysql_affected_rows($this->_link);
			}
			$this->_line = 0;
		}
	}
	
	public function next ()
	{
		$this->_line++;
		$this->_current = mysql_fetch_assoc($this->_result);
	}

	public function key ()
	{
		return $this->_line;
	}
	
	public function pipe($in)
	{
		return $this->__invoke($in);
	}

	public function valid ()
	{
		return ($this->_result === true ||
		        ($this->_valid != 0 && $this->_line <= $this->_valid));
	}

	public function rewind ()
	{
		/**
		 * @todo B110103 check if $this->_current == false (more performance?)
		 */
		if ($this->_valid == 0)
		{
				$this->_current = false;
		}
		else if ($this->_line != 1)
		{
			mysql_data_seek($this->_result, 0);		// goto first line
			$this->_line = 1;						// reset counter
			$this->_current = mysql_fetch_assoc($this->_result);
		}
	}

	function __construct($statement, $link) {
		
		$this->_link = $link;
		
		$pattern = "@:([\w]*)@";
		preg_match_all($pattern, $statement, $match);
		$statement = preg_replace($pattern, "?", $statement);
		$this->_statement = $statement;
		
		if (!empty($match[0]))
		{
			$this->_map = array_flip($match[1]);
			$this->_statementName = "rpd_" . md5($this->_statement);
			mysql_query( "PREPARE `" . $this->_statementName
			           . '` FROM "' . $this->_statement . '"', $this->_link);
		}
		else
		{
			$this->execute();
		}
		
		parent::__construct($statement, $link);
		
		$this->_error["code"]    = mysql_errno();
		$this->_error["message"] = mysql_error();
		
	}
}

?>